﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Forms;
using Application = System.Windows.Application;

namespace VirtualCOM
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {

        #region 成员变量

        private static string exeFilePath, exeFileName;
        private static NotifyIcon trayIcon;
        private static MenuItem autoRunMenuItem;
        private static int Port = 8080;
        private static string IP = "172.0.0.1";
        private static bool isAutoStart = false;
        private static string comNameA, comNameB;
        private static TcpManager tcpManager;
        private static SerialPortManager serialPortManager;
        private static MainWindow mainWindow;

        #endregion

        #region 程序启动

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            //exeFilePath = Process.GetCurrentProcess().MainModule.FileName;
            //exeFileName = System.IO.Path.GetFileName(exeFilePath);

            //int.TryParse(ConfigurationManager.AppSettings["Port"], out Port);
            //IP = ConfigurationManager.AppSettings["IP"];
            //bool.TryParse(ConfigurationManager.AppSettings["AutoStart"], out isAutoStart);

            //comNameA = ConfigurationManager.AppSettings["ComNameA"];
            //comNameB = ConfigurationManager.AppSettings["ComNameB"];

            //VSPDManager.DeleteAll();

            //string[] comNames = SerialPort.GetPortNames();
            //if (comNames.Contains(comNameA) || comNames.Contains(comNameB))
            //{
            //    VSPDManager.DeleteAll();
            //    if (comNames.Contains(comNameA) || comNames.Contains(comNameB))
            //    {
            //        System.Windows.MessageBox.Show("串口名已被占用，本次启动失败后将会自动清理虚拟串口; 如仍旧与物理串口冲突 请修改配置文件！");
            //        Application.Current.Shutdown(0);
            //        return;
            //    }
            //}
            //bool success = false;
            //if (comNameA != null && comNameB != null)
            //    success = VSPDManager.CreatePair(comNameA, comNameB);
            //if (!success)
            //{
            //    System.Windows.MessageBox.Show("创建虚拟串口失败！");
            //    Application.Current.Shutdown(0);
            //    return;
            //}

            bool isAutoRun = IsAutoRun(exeFilePath, exeFileName);
            if (!isAutoRun && isAutoStart)
                SetAutoRun(exeFilePath, exeFileName, true);
            if (isAutoRun && !isAutoStart)
                SetAutoRun(exeFilePath, exeFileName, false);

            InitialTray();

            //InitTCPManager();
            //InitSerialPortManager();
        }

        #endregion

        #region 程序退出

        protected override void OnExit(ExitEventArgs e)
        {
            base.OnExit(e);
            VSPDManager.DeleteAll();
            tcpManager?.Close();
            serialPortManager?.Close();
        }

        #endregion

        #region 托盘图标


        /// <summary>
        /// 初始化托盘图标
        /// </summary>
        private static void InitialTray()
        {
            //设置托盘的各个属性
            trayIcon = new NotifyIcon();
           // trayIcon.BalloonTipText = "成功创建虚拟串口" + comNameA + ":" + comNameB;
            trayIcon.Text = "VirtualCOM";
            trayIcon.Icon = new System.Drawing.Icon(Environment.CurrentDirectory + "\\Resources\\SerialPort.ico");
            trayIcon.Visible = true;
            //trayIcon.ShowBalloonTip(2000);
            trayIcon.MouseClick += NotifyIcon_MouseClick;

            //显示主窗口
            MenuItem showMenuItem = new MenuItem("设置");
            showMenuItem.Click += NotifyIcon_MouseClick;

            //自启动菜单项
            autoRunMenuItem = new MenuItem(isAutoStart ? "取消开机自启" : "开机自启");
            autoRunMenuItem.Click += AutoStart_Click;
            //退出菜单项
            MenuItem exitMenuItem = new MenuItem("退出");
            exitMenuItem.Click += Exit_Click;

            //关联托盘控件
            MenuItem[] menuItems = new MenuItem[] { showMenuItem, autoRunMenuItem, exitMenuItem };
            trayIcon.ContextMenu = new ContextMenu(menuItems);
        }

        private static void Exit_Click(object sender, EventArgs e)
        {
            Application.Current.Shutdown(0);
        }

        private static void AutoStart_Click(object sender, EventArgs e)
        {
            isAutoStart = !isAutoStart;

            ConfigHelper.UpdateConfig("AutoStart", isAutoStart.ToString());
            if (!IsAutoRun(exeFilePath, exeFileName) && isAutoStart)
                SetAutoRun(exeFilePath, exeFileName, true);
            if (IsAutoRun(exeFilePath, exeFileName) && !isAutoStart)
                SetAutoRun(exeFilePath, exeFileName, false);
            autoRunMenuItem.Text = isAutoStart ? "取消开机自启" : "开机自启";
        }

        private static void NotifyIcon_MouseClick(object sender, EventArgs e)
        {
            if (mainWindow == null)
            {
                mainWindow = new MainWindow();
                mainWindow.Closed += OnMainWindowClosed;
                mainWindow.Show();
            }
            else
            {
                if (mainWindow.WindowState == WindowState.Minimized)
                    mainWindow.WindowState = WindowState.Normal;
                mainWindow.Activate();
            }

        }

        private static void OnMainWindowClosed(object sender, EventArgs e)
        {
            mainWindow = null;
        }

        #endregion

        #region 开机自启

        /// <summary>
        /// 设置程序开机启动
        /// </summary>
        /// <param name="strAppPath">应用程序exe所在文件夹</param>
        /// <param name="strAppName">应用程序exe名称</param>
        /// <param name="bIsAutoRun">自动运行状态</param>
        public static void SetAutoRun(string strAppPath, string strAppName, bool bIsAutoRun)
        {
            try
            {
                if (string.IsNullOrEmpty(strAppPath)
                  || string.IsNullOrEmpty(strAppName))
                {
                    throw new Exception("应用程序路径或名称为空！");
                }
                RegistryKey reg = Registry.LocalMachine;
                RegistryKey run = reg.CreateSubKey(@"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\");
                if (bIsAutoRun)
                {
                    run.SetValue(strAppName, strAppPath);
                }
                else
                {
                    if (null != run.GetValue(strAppName))
                    {
                        run.DeleteValue(strAppName);
                    }
                }
                run.Close();
                reg.Close();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }

        /// <summary>
        /// 判断是否开机启动
        /// </summary>
        /// <param name="strAppPath">应用程序路径</param>
        /// <param name="strAppName">应用程序名称</param>
        /// <returns></returns>
        public static bool IsAutoRun(string strAppPath, string strAppName)
        {
            try
            {
                RegistryKey reg = Registry.LocalMachine;
                RegistryKey software = reg.OpenSubKey(@"SOFTWARE");
                RegistryKey run = reg.OpenSubKey(@"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\");
                object key = run.GetValue(strAppName);
                software.Close();
                run.Close();
                if (null == key || !strAppPath.Equals(key.ToString()))
                {
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }
        #endregion

        #region TCP
        private static void InitTCPManager()
        {
            tcpManager = new TcpManager();
            tcpManager.IP = IP;
            tcpManager.Port = Port;
            tcpManager.DataReceived += OnTcpDataReceived;

            try
            {
                tcpManager.Connect();
            }
            catch (Exception ex)
            {
                tcpManager = null;
                Trace.TraceError(ex.ToString());
                System.Windows.MessageBox.Show(ex.ToString());
            }
        }

        private static void OnTcpDataReceived(byte[] bytes)
        {
            serialPortManager?.Send(bytes);
            string message = Encoding.UTF8.GetString(bytes);
            Trace.TraceInformation(message);
        }
        #endregion

        #region TCP
        private static void InitSerialPortManager()
        {
            serialPortManager = new SerialPortManager();
            serialPortManager.ComName = comNameB;
            serialPortManager.BaudRate = 115200;
            serialPortManager.DataReceived += OnSerialPortDataReceived;

            try
            {
                serialPortManager.Open();
            }
            catch (Exception ex)
            {
                serialPortManager = null;
                Trace.TraceError(ex.ToString());
                System.Windows.MessageBox.Show(ex.ToString());
            }
        }

        private static void OnSerialPortDataReceived(byte[] bytes)
        {
            tcpManager?.Send(bytes);
            string message = Encoding.UTF8.GetString(bytes);
            Trace.TraceInformation(message);
        }
        #endregion

    }
}
